﻿#include "can_interface.h"

CAN::CAN()
{
    inicpp::IniManager Interface_ini("config.ini");
    m_deviceType = Interface_ini["can"].toString("devicetype");
    m_deviceIndex = Interface_ini["can"].toInt("deviceindex");
    m_canIndex = Interface_ini["can"].toInt("canindex");
    if (LCAN_OpenDevice(deviceType, deviceIndex) != LCAN_STATUS_OK)
    {
        throw std::runtime_error("Open CAN device Failed");
    }

    int accCode = Interface_ini["can"].toInt("acccode");
    int accMask = Interface_ini["can"].toInt("accmask");
    int filter = Interface_ini["can"].toInt("filter");
    int timing0 = Interface_ini["can"].toInt("timing0");
    int timing1 = Interface_ini["can"].toInt("timing1");
    int mode = Interface_ini["can"].toInt("mode");
    PLCAN_INIT_CONFIG canInitCfg;
    memset(&canInitCfg, 0, sizeof(LCAN_INIT_CONFIG));
    canInitCfg.accCode = accCode;
    canInitCfg.accMask = accMask;
    canInitCfg.filter = filter;
    canInitCfg.timing0 = timing0;
    canInitCfg.timing1 = timing1;
    canInitCfg.mode = mode;
    if (LCAN_InitCAN(m_deviceType, m_deviceIndex, m_canIndex, &canInitCfg) <= 0)
    {
        LCAN_CloseDevice(m_deviceType, m_deviceIndex);
        throw std::runtime_error("Init CAN device Failed");
    }
    m_RxTxThreadRunning.store(true);
    int rxfifosize = Interface_ini["can"].toInt("rxfifosize");
    int txfifosize = Interface_ini["can"].toInt("txfifosize");
    m_RxFifo.init(rxfifosize);
    m_TxFifo.init(txfifosize);
}
CAN::~CAN()
{
    RxTxThreadStop();
    if (m_RxTxThread.joinable())
    {
        m_RxTxThread.join();
    }
    LCAN_CloseDevice(m_deviceType, m_deviceIndex);
}
void CAN::RxTxThreadStart()
{
    m_RxTxThread = std::thread([&]
                               {
		while(m_RxTxThreadRunning,load())
        {
            int rxbuflen = LCAN_GetReceiveNum(m_deviceType, m_deviceIndex, m_canIndex, 0);
            if (rxbuflen > 0)
            {
                LCAN_CAN_OBJ *pdata = new LCAN_CAN_OBJ[rxbuflen];
                LCAN_Receive(m_deviceType, m_deviceIndex, m_canIndex, pdata, rxbuflen, 0);
                m_RxFifo.write(pdata, rxbuflen);
                delete[] pdata;
            }
            if (!m_TxFifo.isEmpty())
            {
                int txbuflen = m_TxFifo.count();
                LCAN_CAN_OBJ *pdata = new LCAN_CAN_OBJ[txbuflen];
                LCAN_Transmit(m_deviceType, m_deviceIndex, m_canIndex, pdata, txbuflen);
                delete[] pdata;
            }
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        } });
    // m_RxTxThread.detach();
}
void CAN::RxTxThreadStop()
{
    m_RxTxThreadRunning.store(false);
}
int CAN::Transmit(LCAN_CAN_OBJ *data, int count)
{
    return m_RxFifo.read(data, count);
}
int CAN::Receive(LCAN_CAN_OBJ *data, int count)
{
    return m_TxFifo.write(data, count);
}
